<template>
	<view class="chat-container">
		<!-- 聊天记录区域 -->
		<view class="message-list">
			<view style="flex-grow: 1; flex-shrink: 1;"></view>
			<view class="list">
				<view class="item" :class="[item.type]" v-for="item in messages">
					<view class="user" v-if="item.type==='user'">
						<view class="text">
							{{item.content}}
						</view>
					</view>
					<view class="ai" v-if="item.type==='ai'">
						<view class="text">
							{{item.content}}
						</view>
					</view>
					<view class="promote" v-if="item.type==='promote'">
						<view @click="postPromote(promote.content)" class="text" v-for="promote in item.list">
							{{promote.content}}
						</view>
					</view>

				</view>
			</view>
		</view>

		<!-- 输入框区域 -->
		<view class=" input-container">
			<input v-model="message" class="input-box" placeholder="请输入消息" :disabled="isSending" />
			<button @click="sendMessage" class="send-btn" :disabled="isSending">发送</button>
		</view>
	</view>
</template>

<script>
	import encoding from "@/tool/encoding.js"
	export default {
		data() {
			return {
				isComplete: true,
				messages: [], // 消息列表
				message: '制定一份适合初学者的前端开发职业规划', // 当前输入的消息
				isSending: false, // 是否正在发送消息
				secretKey: 'pat_dC87V7t7ajNL7mtmZMcoINYtg2PG1UAuyubDiit2vnMxksnWVOraVfp0eFCzlYsR',
				isDone: true
			};
		},
		onLoad() {
			let index = 0
			this.messages.push({
				type: "promote",
				list: [{
					content: "分享一份前端开发的职业规划大纲"
				}, {
					content: "制定一份适合初学者的前端开发职业规划"
				}, {
					content: "前端开发职业发展路径是怎样的"
				}]
			})
		},
		methods: {
			sendMessage() {
				this.isDone = false
				const text = this.message
				this.message = ""
				this.messages.push({
					type: "user",
					content: text
				})
				const index = this.messages.push({
					type: "ai",
					content: ""
				})
				const index2 = this.messages.push({
					type: "promote",
					list: []
				})
				if (!this.isComplete) {
					return uni.showToast({
						title: "对话还未完成",
						icon: "none"
					})
				}
				const requestTask = uni.request({
					url: "https://api.coze.cn/v3/chat?conversation_id",
					method: "POST",
					// #ifdef MP-WEIXIN
					enableChunked: true,
					//#endif
					header: {
						"Content-Type": "application/json",
						"Authorization": `Bearer ${this.secretKey}`
					},
					data: {
						stream: true,
						bot_id: "7487503987659833380",
						user_id: uni.getStorageSync("token"),
						"additional_messages": [
							...this.messages.filter(item => item.type === "user" || item.type === "ai")
							.map(item => {
								if (item.type === "user") {
									return {
										"role": "user",
										"content": item.content,
										"content_type": "text"
									}
								} else {
									return {
										"role": "assistant",
										"content": item.content,
										"content_type": "text"
									}
								}

							}), {
								"role": "user",
								"content": text,
								"content_type": "text",
								"type": "answer",
							}
						]
					},
					success: (res) => {
						console.log(res);
					}
				})
				// #ifdef MP-WEIXIN
				requestTask.onChunkReceived((res) => {
					let chunkText = this.decodeUint8Array(res.data);
					const result = this.parseSSEMessages(chunkText)

					result.forEach(item => {
						if (item.event === "conversation.message.delta" && item.data.type === "answer") {
							this.messages[index - 1].content += item.data.content
						}
						if (item.event === "conversation.message.completed" && item.data.type ===
							"follow_up") {
							this.messages[index2 - 1].list.push({
								content: item.data.content
							})
						}
						if (item.event === "done") {
							this.isDone = true
							console.log(this.messages);
						}
					})



				});
				//#endif
			},
			getRetrieve(conversation_id, chat_id) {
				uni.request({
					url: "https://api.coze.cn/v3/chat/retrieve",
					header: {
						"Content-Type": "application/json",
						"Authorization": `Bearer ${this.secretKey}`
					},
					data: {
						conversation_id,
						chat_id
					},
					success: (res) => {
						const data = res.data
						if (data?.data?.status !== "completed") {
							setTimeout(() => {
								this.getRetrieve(conversation_id, chat_id)
							}, 200)
						} else {
							this.getMessageList(conversation_id, chat_id)
						}

					},
					fail: () => {
						uni.showToast({
							title: "接受信息失败",
							icon: "error"
						})
						this.isComplete = true
					},
				})
			},
			getMessageList(conversation_id, chat_id) {
				uni.request({
					url: "https://api.coze.cn/v3/chat/message/list",
					header: {
						"Content-Type": "application/json",
						"Authorization": `Bearer ${this.secretKey}`
					},
					data: {
						conversation_id,
						chat_id
					},
					success: (res) => {
						const data = res.data
						if (data.data) {
							const follow_up_list = {
								type: "promote",
								list: []
							}
							data.data.forEach(item => {
								if (item.type === "answer") {
									this.messages.push({
										type: "ai",
										content: item.content
									})
								}
								if (item.type === "follow_up") {
									follow_up_list.list.push({
										content: item.content
									})
								}
							})
							if (follow_up_list.list.length) {
								this.messages.push(follow_up_list)
							}
						}
					},
					complete: () => {
						this.isComplete = true
					}
				})
			},
			postPromote(text) {
				this.message = text
				this.sendMessage()
			},
			decodeUint8Array(uint8Array) {
				const data16 = this.buf2hex(uint8Array);
				const requestData = this.hexToStr(data16)
				return requestData
			},
			buf2hex(arrayBuffer) {
				return Array.prototype.map.call(new Uint8Array(arrayBuffer), x => ('00' + x.toString(16)).slice(-2)).join(
					'');
			},
			/**
			 * 十六进制字符串转中文
			 * @param {String} hex 为十六进制字符串
			 * @return {String} 包含中文的字符串
			 */
			hexToStr(hex) {
				// 去掉字符串首尾空格
				let trimedStr = hex.trim()
				// 判断trimedStr前两个字符是否为0x，如果是则截取从第三个字符及后面所有，否则返回全部字符
				let rawStr = trimedStr.substr(0, 2).toLowerCase() === "0x" ? trimedStr.substr(2) : trimedStr
				// 得到rawStr的长度
				let len = rawStr.length
				// 如果长度不能被2整除，那么传入的十六进制值有误，返回空字符
				if (len % 2 !== 0) {
					return ""
				}
				let curCharCode // 接收每次循环得到的字符
				let resultStr = [] // 存转换后的十进制值数组
				for (let i = 0; i < len; i = i + 2) {
					curCharCode = parseInt(rawStr.substr(i, 2), 16)
					resultStr.push(curCharCode)
				}
				// encoding为空时默认为utf-8
				let bytesView = new Uint8Array(resultStr) // 8 位无符号整数值的类型化数组
				let str = new encoding.TextDecoder().decode(bytesView)
				return str
			},
			parseSSEMessages(message) {
				// First split the entire message into individual SSE messages
				const rawMessages = message.split(/\n\n+/);
				const parsedMessages = [];

				for (const rawMessage of rawMessages) {
					// Skip empty messages
					if (!rawMessage.trim()) continue;

					// Check for the special done event
					if (rawMessage === 'event:done\ndata:"[DONE]"') {
						parsedMessages.push({
							event: 'done',
							data: '[DONE]'
						});
						continue;
					}

					// Parse individual message
					const parts = rawMessage.split('\n');
					let eventType = 'message'; // default event type
					let data = null;

					for (const part of parts) {
						if (part.startsWith('event:')) {
							eventType = part.substring(6).trim();
						} else if (part.startsWith('data:')) {
							const dataStr = part.substring(5).trim();
							try {
								data = JSON.parse(dataStr);
							} catch (e) {
								// If JSON parsing fails, keep the raw string
								data = dataStr;
							}
						}
					}

					if (eventType || data !== null) {
						parsedMessages.push({
							event: eventType,
							data
						});
					}
				}

				return parsedMessages;
			}
		}
	};
</script>

<style scoped lang="scss">
	/* 页面容器 */
	.chat-container {
		display: flex;
		flex-direction: column;
		height: 100vh;
		// #ifdef H5
		height: calc(100vh - 44px);
		//#endif
		background-color: #f0f0f0;
	}

	/* 消息列表 */
	.message-list {
		flex: 1;
		padding: 10px;
		overflow-y: auto;
		background-color: #fff;
		border-bottom: 1px solid #ddd;
		display: flex;
		flex-direction: column-reverse;

		.list {
			display: flex;
			flex-direction: column;
			gap: 25rpx 0;

			.item {
				display: flex;

				&.user {
					justify-content: flex-end;

					.user {
						max-width: 500rpx;
					}
				}

				&.ai {
					.ai {
						max-width: 500rpx;

						.text {
							background-color: #ddd;
							color: #007aff;
						}
					}
				}


				.text {
					padding: 10rpx 15rpx;
					background-color: #007aff;
					color: #fff;
					border-radius: 10rpx;
					white-space: pre-wrap;
				}

				.promote {
					padding-top: 30rpx;
					display: flex;
					flex-wrap: wrap;
					gap: 25rpx;

					.text {
						border: 1rpx solid #ccc;
						background-color: #fff;
						color: #000;
					}
				}
			}

		}
	}

	.message {
		max-width: 70%;
		padding: 8px 12px;
		border-radius: 15px;
		margin-bottom: 10px;
		font-size: 14px;
		line-height: 1.5;
	}

	.message.user {
		background-color: #007aff;
		color: white;
		align-self: flex-end;
		margin-left: auto;
	}

	.message.other {
		background-color: #e1e1e1;
		color: #333;
		align-self: flex-start;
	}

	.message-text {
		word-wrap: break-word;
	}

	/* 输入区域 */
	.input-container {
		display: flex;
		padding: 10px;
		background-color: #fff;
		border-top: 1px solid #ddd;
	}

	.input-box {
		flex: 1;
		height: 40px;
		padding: 0 10px;
		border-radius: 20px;
		border: 1px solid #ddd;
		font-size: 14px;
		background-color: #f9f9f9;
	}

	.send-btn {
		margin-left: 10px;
		padding: 0 15px;
		height: 40px;
		border-radius: 20px;
		background-color: #007aff;
		color: white;
		font-size: 14px;
		border: none;
		cursor: pointer;
		transition: background-color 0.3s;
	}

	.send-btn:disabled {
		background-color: #b0b0b0;
	}

	.send-btn:hover:not(:disabled) {
		background-color: #005bb5;
	}
</style>